package nmf;

import java.util.Comparator;
import java.util.PriorityQueue;

import org.ejml.simple.SimpleMatrix;

public class FeatureSparsenessNMFTool extends FeatureRelevanceTool {
   
   @Override
   public String toString() {
      return "Feature Sparseness NMF Tool";
   }
   
   @Override
   public int getNumIterations(final SimpleMatrix V) {
      return 1;
   }
   
   @Override
   public Integer[] getRelevantFeatures(final SimpleMatrix V, final int category,
         final int numberOfFeatures) {
      final Integer[] relevantFeatures = new Integer[numberOfFeatures];
      final PriorityQueue<wordRelevance> que = new PriorityQueue<wordRelevance>(
            V.numRows(), new Comparator<wordRelevance>() {
               @Override
               public int compare(final wordRelevance arg0, final wordRelevance arg1) {
                  if (arg0.zeroRelevance - arg1.zeroRelevance != 0) {
                     return (int) Math.signum(arg1.zeroRelevance -
                           arg0.zeroRelevance);
                  }
                  else {
                     return (int) Math.signum(arg1.hardRelevance -
                           arg0.hardRelevance);
                  }
               }
            });
      
      for (int rowNum = 0; rowNum < V.numRows(); rowNum++) {
         que.add(new wordRelevance(getWordRelevance(V, rowNum, category),
               rowNum, -numZeroes(V, rowNum, category, false)));//((double)numZeroes(V, rowNum, category, true) / (trainingSetSize - map.get(category))) - 
         //((double)numZeroes(V, rowNum, category, false) / map.get(category))));
      }
      
      for (int currentWord = 0; currentWord < relevantFeatures.length; currentWord++) {
         relevantFeatures[currentWord] = que.remove().row;
      }
      
      return relevantFeatures;
   }
   
   public class wordRelevance {
      double hardRelevance, zeroRelevance;
      int row;
      
      public wordRelevance(final double hardRelevance, final int row, final double zeroRelevance) {
         this.hardRelevance = hardRelevance;
         this.row = row;
         this.zeroRelevance = zeroRelevance;
      }
   }
   
   public int numZeroes(final SimpleMatrix V, final int rowNum, final int category,
         final boolean anti) {
      int count = 0;
      for (int crntColumn = 0; crntColumn < trainClass.length; crntColumn++) {
         if (!anti && V.get(rowNum, crntColumn) == 0 &&
               trainClass[crntColumn] == category) {
            count++;
         }
         else if (anti && V.get(rowNum, crntColumn) == 0 &&
               trainClass[crntColumn] != category) {
            count++;
         }
      }
      
      return count;
   }
   
}
